home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PROG_TOO / C027B.ZIP / JAS / GEN.C < prev    next >
Text File  |  1990-03-30  |  10KB  |  430 lines

  1.  
  2. /*
  3.  * Copyright (c) 1988 by Sozobon, Limited.  Author: Joseph M Treat
  4.  *
  5.  * Permission is granted to anyone to use this software for any purpose
  6.  * on any computer system, and to redistribute it freely, with the
  7.  * following restrictions:
  8.  * 1) No charge may be made other than reasonable charges for reproduction.
  9.  * 2) Modified versions must be clearly marked as such.
  10.  * 3) The authors are not responsible for any harmful consequences
  11.  *    of using this software, even if they result from defects in it.
  12.  */
  13.  
  14. #include "jas.h"
  15.  
  16. geninst( sp )
  17.     STMT *sp;
  18. {
  19.     register OPERAND *op;
  20.     register char *cp;
  21.     register short nbits = 0;
  22.     register long fill = 0L;
  23.     register short emode, ereg;
  24.     OPERAND *eff[2];
  25.     int which, do_immediate = 0;
  26.     CBUF *cbp;
  27.     extern int line;
  28.     extern long newdot;
  29.     extern Optimize;
  30.     extern CBUF *generate();
  31.  
  32.     findinst( sp );
  33.     eff[0] = eff[1] = (OPERAND *) NULL;
  34.  
  35.     if ( sp->op0 && sp->op0->mode == O_IMM )
  36.         do_immediate = 1;
  37.  
  38.     for ( cp = sp->inst->format; *cp; cp++ ) {
  39.         if ( *cp == 'o' ) {
  40.             do {
  41.                 cp++;
  42.                 fill = ( fill << 3 ) | ( *cp - '0' );
  43.                 nbits += 3;
  44.             } while ( cp[1] >= '0' && cp[1] <= '7' );
  45.         } else if ( *cp == 'x' ) {
  46.             do {
  47.                 cp++;
  48.                 if ( *cp <= '9' )
  49.                     fill = ( fill << 4 ) | ( *cp - '0' );
  50.                 else
  51.                     fill = ( fill << 4 ) | (*cp - 'a' + 10);
  52.                 nbits += 4;
  53.             } while ( (cp[1] >= '0' && cp[1] <= '9') ||
  54.                         (cp[1] >= 'a' && cp[1] <= 'f'));
  55.  
  56.         } else if ( *cp == '0' ) {
  57.             fill = ( fill << 1 );
  58.             nbits++;
  59.         } else if ( *cp == '1' ) {
  60.             fill = ( fill << 1 ) | 1;
  61.             nbits++;
  62.         } else if ( *cp == '$' ) {
  63.             switch ( *++cp ) {
  64.             case 's':
  65.                 fill = ( fill << 2 ) |
  66.                         ( ( sp->misc & (S_BWL) ) >> 1 );
  67.                 nbits += 2;
  68.                 break;
  69.             case 'c':
  70.                 fill = ( fill << 4 ) | ( sp->misc >> 4 );
  71.                 nbits += 4;
  72.                 break;
  73.             case 'd':
  74.                 fill = ( fill << 1 ) |
  75.                         ( ( sp->misc & 0x8 ) >> 3 );
  76.                 nbits++;
  77.                 break;
  78.             }
  79.         } else if ( *cp == '%' ) {
  80.             OPERAND *mp;
  81.  
  82.             cp++;
  83.             if ( *cp == '0' ) {
  84.                 which = 0;
  85.                 op = sp->op0;
  86.                 cp++;
  87.             } else if ( *cp == '1' ) {
  88.                 which = 1;
  89.                 op = sp->op1;
  90.                 cp++;
  91.             } else if ( *cp >= 'A' && *cp <= 'Z' ) {
  92.                 which = 1;
  93.                 op = sp->op1;
  94.             } else /* if ( *cp >= 'a' && *cp <= 'z' ) */ {
  95.                 which = 0;
  96.                 op = sp->op0;
  97.             }
  98.  
  99.             switch ( *cp ) {
  100.             case 'r':
  101.                 fill = ( fill << 3 ) | (op->reg & 0x7 );
  102.                 nbits += 3;
  103.                 break;
  104.             case 'q':
  105.                 fill = ( fill << 3 ) | (op->expr.value & 0x7);
  106.                 nbits += 3;
  107.                 do_immediate = 0;
  108.                 break;
  109.             case 'k':
  110.                 fill = ( fill << 8 ) | (op->expr.value & 0xff);
  111.                 nbits += 8;
  112.                 do_immediate = 0;
  113.                 break;
  114.             case 'v':
  115.                 fill = ( fill << 4 ) | (op->expr.value & 0x0f);
  116.                 nbits += 4;
  117.                 do_immediate = 0;
  118.                 break;
  119.             case 'm':
  120.                 if ( nbits % 8 )
  121.                     error( line, "internal alignment" );
  122.                 generate( nbits, GENSTMT, fill, (SYM *) NULL );
  123.                 nbits = 0;
  124.                 fill = 0L;
  125.                 if ( op->mode == O_DN || op->mode == O_AN )
  126.                     op->expr.value = 1L << op->reg;
  127.                 op->mode = O_REGS;
  128.                 mp = ( which == 0 ) ? sp->op1 : sp->op0;
  129.                 if ( mp->mode == O_PRE ) {
  130.                     /*
  131.                      * we must reverse the bits !GAG!
  132.                      */
  133.                     int i, k;
  134.  
  135.                     k = op->expr.value;
  136.                     for ( i = 0; i < 16; i++ ) {
  137.                         fill <<= 1;
  138.                         if ( k & 1 )
  139.                             fill |= 1;
  140.                         k >>= 1;
  141.                     }
  142.                     generate( 16, GENVALUE, fill,
  143.                                 (SYM *) NULL );
  144.                     fill = 0L;
  145.                 } else {
  146.                     generate( 16, GENVALUE, op->expr.value,
  147.                                 (SYM *) NULL );
  148.                 }
  149.                 break;
  150.             case 'd':
  151.                 if (! Optimize ) {
  152.                     fill <<= 8;
  153.                     nbits += 8;
  154.                     if ( nbits % 8 )
  155.                         error( line,
  156.                             "internal alignment" );
  157.                     generate( nbits, GENSTMT, fill,
  158.                                 (SYM *) NULL);
  159.                     nbits = 0;
  160.                     fill = 0L;
  161.                     generate( 16, GENPCREL, op->expr.value,
  162.                                 op->expr.psym);
  163.                     break;
  164.                 }
  165.                 if ( nbits != 8 )
  166.                     error( line, "internal alignment" );
  167.                 cbp = generate(8, GENBRNCH, fill, (SYM *) NULL);
  168.                 nbits = 0;
  169.                 fill = 0L;
  170.  
  171.                 generate( 8, GENPCREL, op->expr.value,
  172.                                 op->expr.psym);
  173.                 add_brnch( cbp, newdot );
  174.                 break;
  175.             case 'D':
  176.                 if ( nbits % 8 )
  177.                     error( line, "internal alignment" );
  178.                 generate( nbits, GENSTMT, fill, (SYM *) NULL );
  179.                 nbits = 0;
  180.                 fill = 0L;
  181.                 generate( 16, GENPCREL, op->expr.value,
  182.                                 op->expr.psym);
  183.                 break;
  184.             case 'L':
  185.                 if ( nbits % 8 )
  186.                     error( line, "internal alignment" );
  187.                 generate( nbits, GENSTMT, fill, (SYM *) NULL );
  188.                 nbits = 0;
  189.                 fill = 0L;
  190.                 generate( 16, GENVALUE, op->expr.value,
  191.                                 (SYM *) NULL );
  192.                 break;
  193.             case 'f':
  194.             case 'e':
  195.                 emode = ereg = 0;
  196.                 switch ( op->mode ) {
  197.                 case O_DN:
  198.                     emode = 0x0;
  199.                     ereg = op->reg & 0x7;
  200.                     break;
  201.                 case O_AN:
  202.                     emode = 0x1;
  203.                     ereg = op->reg & 0x7;
  204.                     break;
  205.                 case O_INDR:
  206.                     emode = 0x2;
  207.                     ereg = op->reg & 0x7;
  208.                     break;
  209.                 case O_POST:
  210.                     emode = 0x3;
  211.                     ereg = op->reg & 0x7;
  212.                     break;
  213.                 case O_PRE:
  214.                     emode = 0x4;
  215.                     ereg = op->reg & 0x7;
  216.                     break;
  217.                 case O_DISP:
  218.                     emode = 0x5;
  219.                     ereg = op->reg & 0x7;
  220.                     eff[which] = op;
  221.                     break;
  222.                 case O_INDX:
  223.                     emode = 0x6;
  224.                     ereg = op->reg & 0x7;
  225.                     eff[which] = op;
  226.                     break;
  227.                 case O_ABS:
  228.                     emode = 0x7;
  229.                     ereg = 0x1;
  230.                     eff[which] = op;
  231.                     break;
  232.                 case O_PCRL:
  233.                     emode = 0x7;
  234.                     ereg = 0x2;
  235.                     eff[which] = op;
  236.                     break;
  237.                 case O_PCIX:
  238.                     emode = 0x7;
  239.                     ereg = 0x3;
  240.                     eff[which] = op;
  241.                     break;
  242.                 case O_IMM:
  243.                     emode = 0x7;
  244.                     ereg = 0x4;
  245.                     break;
  246.                 }
  247.                 if ( *cp == 'e' ) {
  248.                     fill = ( fill << 3 ) | emode;
  249.                     fill = ( fill << 3 ) | ereg;
  250.                 } else {
  251.                     fill = ( fill << 3 ) | ereg;
  252.                     fill = ( fill << 3 ) | emode;
  253.                 }
  254.                 nbits += 6;
  255.                 break;
  256.             }
  257.         } 
  258.     }
  259.     if ( nbits % 8 )
  260.         error( line, "internal alignment" );
  261.     if ( nbits ) {
  262.         generate( nbits, GENSTMT, fill, (SYM *) NULL );
  263.         nbits = 0;
  264.     }
  265.     fill = 0L;
  266.     if ( do_immediate ) {
  267.         int size;
  268.         op = sp->op0;
  269.  
  270.         size = sp->misc & (S_BWL);
  271.         if ( size == S_B ) {
  272.             generate( 8, GENVALUE, 0L, (SYM *) NULL );
  273.         }
  274.         generate( size << 3, GENRELOC, op->expr.value, op->expr.psym );
  275.     }
  276.     for ( which = 0; which <= 1; which++ ) {
  277.         if ( eff[which] == (OPERAND *) NULL )
  278.             continue;
  279.         op = eff[which];
  280.         switch ( op->mode ) {
  281.         case O_DISP:
  282.             generate( 16, GENRELOC, op->expr.value, op->expr.psym );
  283.             break;
  284.         case O_INDX:
  285.             fill = op->inx & 0x0f;
  286.             fill = ( fill << 4 ) | ((op->inx & 0x10) >> 1);
  287.             generate(8, GENVALUE, fill, (SYM *) NULL );
  288.             generate( 8, GENRELOC, op->expr.value, op->expr.psym );
  289.             break;
  290.         case O_ABS:
  291.             if ( sp->inst->flags & F_PC )
  292.                 generate( 16, GENPCREL, op->expr.value,
  293.                                 op->expr.psym );
  294.             else
  295.                 generate( 32, GENRELOC, op->expr.value,
  296.                                 op->expr.psym );
  297.             break;
  298.         case O_PCRL:
  299.             generate( 16, GENVALUE, op->expr.value, (SYM *) NULL );
  300.             break;
  301.         case O_PCIX:
  302.             fill = op->inx & 0x0f;
  303.             fill = ( fill << 4 ) | ((op->inx & 0x10) >> 1);
  304.             generate(8, GENVALUE, fill, (SYM *) NULL );
  305.             generate( 8, GENVALUE, op->expr.value, (SYM *) NULL );
  306.             break;
  307.         }
  308.     }
  309. }
  310.  
  311. findinst( sp )
  312.     STMT *sp;
  313. {
  314.     register INST *ip;
  315.     register INST *jp;
  316.  
  317.     ip = sp->inst;
  318.     for ( ; ; ) {
  319.         if (! inst_ok( sp ) ) {
  320.             return;
  321.         }
  322.         jp = ip+1;
  323.         if (! strcmp( jp->mnemon, ip->mnemon ) ) {
  324.             sp->inst = ip = jp;
  325.             continue;
  326.         }
  327.         break;
  328.     }
  329.     Yerror( "illegal instruction" );
  330. }
  331.  
  332. inst_ok( sp )
  333.     register STMT *sp;
  334. {
  335.     register INST *ip = sp->inst;
  336.     register unsigned short size;
  337.     extern Optimize;
  338.  
  339.     if (! Optimize ) {
  340.         /*
  341.          * if we're not optimizing, don't change jsr's to bsr's
  342.          */
  343.         if (! strncmp( ip->mnemon, "jsr", 3 ) )
  344.             if (! strncmp( ip->format, "x61", 3 ) )
  345.                 return -18;
  346.     }
  347.  
  348.     if ( ip->op0 != O_NONE && sp->op0 == (OPERAND *) NULL )
  349.         return -1;
  350.     if ( ip->op1 != O_NONE && sp->op1 == (OPERAND *) NULL )
  351.         return -2;
  352.     if ( sp->op1 && ip->op1 == O_NONE )
  353.         return -3;
  354.     if ( sp->op0 ) {
  355.         if ( ip->op0 == O_NONE )
  356.             return -4;
  357.         if ( ( sp->op0->mode & ip->op0 ) != sp->op0->mode )
  358.             return -5;
  359.     }
  360.     if ( sp->op1 ) {
  361.         if ( ip->op1 == O_NONE )
  362.             return -6;
  363.         if ( ( sp->op1->mode & ip->op1 ) != sp->op1->mode )
  364.             return -7;
  365.     }
  366.     size = sp->misc & (S_BWL);
  367.     if ( ( size & ip->size ) != size )
  368.         return -8;
  369.     if ( ip->flags & F_Q ) {
  370.         long val = sp->op0->expr.value;
  371.  
  372.         if ( sp->op0->expr.psym )
  373.             return -9;
  374.         if ( val < 1 || val > 8 )
  375.             return -10;
  376.     }
  377.     if ( ip->flags & F_MQ ) {
  378.         long val = sp->op0->expr.value;
  379.  
  380.         if ( sp->op0->expr.psym )
  381.             return -11;
  382.         if ( val < -128 || val > 127 )
  383.             return -12;
  384.     }
  385.     if ( ip->flags & F_TV ) {
  386.         long val = sp->op0->expr.value;
  387.  
  388.         if ( sp->op0->expr.psym )
  389.             return -13;
  390.         if ( val < 0 || val > 15 )
  391.             return -14;
  392.     }
  393.     if ( ip->flags & F_TXT ) {
  394.         OPERAND *op = sp->op0;
  395.  
  396.         if ( op->mode == O_DN ) /* the db$c instruction */
  397.             op = sp->op1;
  398.         switch ( op->mode ) {
  399.         case O_DISP: case O_INDX:
  400.             if ( op->expr.psym ) {
  401.                 switch ( op->expr.psym->flags & SEGMT ) {
  402.                 case 0: case TXT:
  403.                     break;
  404.                 default:
  405.                     return -15;
  406.                 }
  407.             }
  408.             break;
  409.         case O_ABS:
  410.             if ( op->expr.psym == (SYM *) NULL )
  411.                 return -16;
  412.             switch ( op->expr.psym->flags & SEGMT ) {
  413.             case 0: case TXT:
  414.                 break;
  415.             default:
  416.                 return -17;
  417.             }
  418.             break;
  419.         }
  420.     }
  421.  
  422.     /*
  423.      * set the default size, if none is specified
  424.      */
  425.     if ( size == 0 )
  426.         sp->misc |= ( ip->flags & (S_BWL) );
  427.  
  428.     return 0;
  429. }
  430.